//
//
//

package qqopenapi_v3

import (
  "crypto/tls"
  "errors"
  "fmt"
  "log"
  "io/ioutil"
  "net/url"
  "net/http"
  "strings"
  . "github.com/ckrissun/go-simplejson"
)

type SNSNetwork struct {
  _iplist   *RandomString
  _ipaddr   string
  _seceret  string
  _sig_name string
}

func NewSNSNetwork(iplist *RandomString, seceret, sig_name string) *SNSNetwork {
  this := &SNSNetwork{}
  if iplist != nil {
    this._iplist = iplist
  } else {
    this._iplist = NewRandomString([]string{DEFAULT_QQ_OPENIP})
  }
  this._ipaddr    = this._iplist.String()
  this._seceret   = seceret
  this._sig_name  = sig_name
  return this
}

func (this *SNSNetwork) mk_send_data(method, url_path string, params url.Values) url.Values {
  sig := hmac_sha1_sig(method, url_path, this._seceret, params)
  params.Set(this._sig_name, sig)
  return params
}

func (this *SNSNetwork) http_send(method, uri string, params url.Values) (*Json, error) {
  
  var resp *http.Response
  var err error

  switch strings.ToLower(method) {
  case "get":
    if params != nil && params.Encode() != "" {
      uri += "?" + params.Encode()
    }
    resp, err = http.Get(uri)
  case "post":
    resp, err = http.PostForm(uri, params)
  default:
    return nil, errors.New(fmt.Sprintf("method invalid: %s", method))
  }

  if err != nil {
    log.Println(err)
    return nil, err
  }
  defer resp.Body.Close()

  var buf []byte
  buf, err = ioutil.ReadAll(resp.Body)
  if err != nil {
    log.Println(err)
    return nil, err
  }

  var js *Json
  js, err = NewJson(buf)
  if err != nil {
    log.Println(err)
  }
  return js, err
}

func (this *SNSNetwork) https_send(method, uri string, params url.Values) (*Json, error) {
  var resp *http.Response
  var err error

  //http://stackoverflow.com/questions/12122159/golang-how-to-do-a-https-request-with-bad-certificate
  var tr = &http.Transport{
    TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  }
  var client = &http.Client{Transport: tr}

  switch strings.ToLower(method) {
  case "get":
    if params != nil && params.Encode() != "" {
      uri += "?" + params.Encode()
    }
    resp, err = client.Get(uri)
  case "post":
    resp, err = client.PostForm(uri, params)
  default:
    return nil, errors.New(fmt.Sprintf("method invalid: %s", method))
  }

  if err != nil {
    log.Println(err)
    return nil, err
  }
  defer resp.Body.Close()

  var buf []byte
  buf, err = ioutil.ReadAll(resp.Body)
  if err != nil {
    log.Println(err)
    return nil, err
  }

  var js *Json
  js, err = NewJson(buf)
  if err != nil {
    log.Println(err)
  }
  return js, err
}

func (this *SNSNetwork) open(method, url_path, protocol string, params url.Values) (*Json, error) {

  var ec_params = this.mk_send_data(method, url_path, params)
  var uri = fmt.Sprintf("%s://%s%s", strings.ToLower(protocol), this._ipaddr, url_path) 

  var data *Json
  var err error

  switch strings.ToLower(protocol) {
  case "http":
    data, err = this.http_send(method, uri, ec_params)
  case "https":
    data, err = this.https_send(method, uri, ec_params)
  default:
    data, err = nil, errors.New(fmt.Sprintln("protocol invalid:", protocol))
    log.Println(err)
  }
  return data, err
}

